home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / lfscheck / checkdir.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-12  |  37.3 KB  |  1,419 lines

  1. /* 
  2.  * checkdir.c --
  3.  *
  4.  *    Routines to allow moving through a files block pointers.
  5.  *
  6.  * Copyright 1989 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/src/cmds/fscheck/RCS/checkdir.c,v 1.29 90/10/10 15:29:03 mendel Exp $ SPRITE (Berkeley)";
  18. #endif not lint
  19.  
  20. #include <option.h>
  21. #include "fscheck.h"
  22. #include <list.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26.  
  27. static  int         lostFoundFileNum = -1;
  28. static    char        pathName[FS_MAX_PATH_NAME_LENGTH];
  29.  
  30. int foundError;
  31. int verbose = 1;
  32. int debug = 0;
  33. int tooBig = 0;
  34. static int        diskFd;
  35.  
  36. Fsdm_FileDescriptor    *rootFDPtr, *lostFoundFDPtr;
  37.  
  38. static int MakePtrAccessible _ARGS_((register DirIndexInfo *indexInfoPtr));
  39. static int GetFirstIndex _ARGS_((int blockNum, register DirIndexInfo *indexInfoPtr));
  40. static int GetNextIndex _ARGS_((register DirIndexInfo *indexInfoPtr));
  41. static void OpenDir _ARGS_((Fsdm_FileDescriptor *fdPtr, FdInfo *fdInfoPtr, DirIndexInfo *indexInfoPtr, Fslcl_DirEntry **dirEntryPtrPtr));
  42. static void NextDirEntry _ARGS_((DirIndexInfo *indexInfoPtr, Fslcl_DirEntry **dirEntryPtrPtr));
  43. static void CloseDir _ARGS_((DirIndexInfo *indexInfoPtr));
  44. static void CheckDir _ARGS_((int fdNum, Fsdm_FileDescriptor *fdPtr, FdInfo *fdInfoPtr, int parentFdNum, int lostDirNum, int *dirOKPtr));
  45.  
  46. #define DIRFULL 2
  47.  
  48.  
  49. /*
  50.  *----------------------------------------------------------------------
  51.  *
  52.  * FetchFileDesc --
  53.  *
  54.  *    Return a file descriptor.
  55.  *
  56.  * Results:
  57.  *    1 if the file descriptor is successfully read or 0 if the descriptor 
  58.  *    was unreadable.
  59.  *
  60.  * Side effects:
  61.  *    A file descriptor may be allocated.
  62.  *
  63.  *----------------------------------------------------------------------
  64.  */
  65. int
  66. FetchFileDesc(fdNum, fdPtrPtr)
  67.     int            fdNum;        /* Number of descriptor to fetch. */
  68.     Fsdm_FileDescriptor    **fdPtrPtr;    /* Where to store ptr to descriptor. */
  69. {
  70.     int bufSize,  j;
  71.     LfsFileDescriptor    *descPtr;
  72.     char *descBuf;
  73.     LfsDescMapEntry *descMapPtr;
  74.  
  75.     if ((fdNum < 0) || (fdNum >= superBlockPtr->descMap.maxDesc)) {
  76.     return 0;
  77.     }
  78.     if (descInfoArray[fdNum].flags & FD_UNREADABLE) {
  79.     return 0;
  80.     }
  81.     bufSize = superBlockPtr->fileLayout.descPerBlock * sizeof(*descPtr);
  82.  
  83.     descBuf = alloca(bufSize);
  84.  
  85.     descMapPtr = DescMapEntry(fdNum);
  86.     if (descMapPtr->flags != LFS_DESC_MAP_ALLOCED) {
  87.     Alloc(*fdPtrPtr,Fsdm_FileDescriptor,1);
  88.     if (tooBig) {
  89.         return 0;
  90.     }
  91.     bzero((char *) *fdPtrPtr, sizeof(Fsdm_FileDescriptor));
  92.     return 1;
  93.     }
  94.     if (DiskRead(diskFd, descMapPtr->blockAddress, bufSize, descBuf)
  95.             != bufSize) {
  96.     return 0;
  97.     }
  98.     descPtr = (LfsFileDescriptor *)descBuf;
  99.     for (j = 0; j < superBlockPtr->fileLayout.descPerBlock; j++) {
  100.     if (!(descPtr->common.flags & FSDM_FD_ALLOC)) {
  101.         break;
  102.     }
  103.     if (descPtr->fileNumber == fdNum) {
  104.         break;
  105.     }
  106.     descPtr++;
  107.     }
  108.     if ((j >= superBlockPtr->fileLayout.descPerBlock) ||
  109.     !(descPtr->common.flags & FSDM_FD_ALLOC) ||
  110.     (descPtr->fileNumber != fdNum)) {
  111.     return 0;
  112.     }
  113.     Alloc(*fdPtrPtr,Fsdm_FileDescriptor,1);
  114.     if (tooBig) {
  115.     return 0;
  116.     }
  117.     bcopy((Address)&(descPtr->common), (Address)*fdPtrPtr, 
  118.       sizeof(Fsdm_FileDescriptor));
  119.     return(1);
  120. }
  121.  
  122.  
  123. /*
  124.  *----------------------------------------------------------------------
  125.  *
  126.  * StoreFileDesc --
  127.  *
  128.  *    Store a file descriptor on disk.
  129.  *
  130.  * Results:
  131.  *    None.
  132.  *
  133.  * Side effects:
  134.  *    An FdCheckInfo struct is allocated.
  135.  *
  136.  *----------------------------------------------------------------------
  137.  */
  138. void
  139. StoreFileDesc(fdNum, fdPtr)
  140.     int            fdNum;
  141.     Fsdm_FileDescriptor    *fdPtr;
  142. {
  143.     extern void panic();
  144.     panic("StoreFileDesc not implemented\n");
  145. }
  146.  
  147. /*
  148.  *----------------------------------------------------------------------
  149.  *
  150.  * MakePtrAccessible --
  151.  *
  152.  *    Make the pointer to the directory entry accessible.
  153.  *
  154.  * Results:
  155.  *    None.
  156.  *
  157.  * Side effects:
  158.  *    *indexInfoPtr modified.
  159.  *
  160.  *----------------------------------------------------------------------
  161.  */
  162. static int
  163. MakePtrAccessible(indexInfoPtr)
  164.     register    DirIndexInfo *indexInfoPtr;
  165. {
  166.     register int         *blockAddrPtr;
  167.     register Fsdm_FileDescriptor    *fdPtr;
  168.  
  169.     fdPtr = indexInfoPtr->fdPtr;
  170.  
  171.     blockAddrPtr = &indexInfoPtr->blockAddr;
  172.  
  173.     if (indexInfoPtr->indexType == INDIRECT) {
  174.     *blockAddrPtr = fdPtr->indirect[0];
  175.     } else {
  176.     *blockAddrPtr = fdPtr->indirect[1];
  177.     }
  178.  
  179.     /*
  180.      * Read first level block in.
  181.      */
  182.     if (indexInfoPtr->firstBlockNil) {
  183.     if (*blockAddrPtr == FSDM_NIL_INDEX) {
  184.         return(1);
  185.     }
  186.     if (DiskRead(diskFd,
  187.               *blockAddrPtr, FS_BLOCK_SIZE,
  188.               indexInfoPtr->firstBlock) != FS_BLOCK_SIZE) {
  189.         fprintf(stderr,"MakePtrAccessible: Read (1) failed block %d\n",
  190.                *blockAddrPtr);
  191.         return(0);
  192.     }
  193.     indexInfoPtr->firstBlockNil = 0;
  194.     }
  195.  
  196.     *blockAddrPtr = *(int *) (indexInfoPtr->firstBlock +
  197.                   sizeof(int) * indexInfoPtr->firstIndex);
  198.     if (indexInfoPtr->indexType == INDIRECT) {
  199.     return(1);
  200.     }
  201.  
  202.     /*
  203.      * Read second level block in.
  204.      */
  205.     if (*blockAddrPtr != FSDM_NIL_INDEX) {
  206.     if (DiskRead(diskFd, 
  207.               *blockAddrPtr, FS_BLOCK_SIZE,
  208.               indexInfoPtr->secondBlock) != FS_BLOCK_SIZE) {
  209.         fprintf(stderr,"MakePtrAccessible: Read (2) failed block %d\n",
  210.                *blockAddrPtr);
  211.         return(0);
  212.     }
  213.     indexInfoPtr->secondBlockNil = 0;
  214.     *blockAddrPtr = *(int *) (indexInfoPtr->secondBlock +
  215.                   sizeof(int) * indexInfoPtr->secondIndex);
  216.     }
  217.     return(1);
  218. }
  219.  
  220.  
  221. /*
  222.  *----------------------------------------------------------------------
  223.  *
  224.  * GetFirstIndex --
  225.  *
  226.  *    Initialize the index structure.  This will set up the index info
  227.  *    structure so that it contains a pointer to the desired block pointer.
  228.  *
  229.  * Results:
  230.  *    1 if could set up the index, 0 if could not.
  231.  *
  232.  * Side effects:
  233.  *    The index structure is initialized.
  234.  *
  235.  *----------------------------------------------------------------------
  236.  */
  237. static int
  238. GetFirstIndex(blockNum, indexInfoPtr)
  239.     int                  blockNum;      /* Where to start indexing. */
  240.     register DirIndexInfo     *indexInfoPtr; /* Index structure to initialize.*/
  241. {
  242.     int            indirectBlock;
  243.     Fsdm_FileDescriptor    *fdPtr;
  244.  
  245.     indexInfoPtr->firstBlockNil = 1;
  246.     indexInfoPtr->secondBlockNil = 1;
  247.     indexInfoPtr->blockNum = blockNum;
  248.     indexInfoPtr->dirDirty = 0;
  249.  
  250.     fdPtr = indexInfoPtr->fdPtr;
  251.  
  252.     if (blockNum < FSDM_NUM_DIRECT_BLOCKS) {
  253.     /*
  254.      * This is a direct block.
  255.      */
  256.     indexInfoPtr->indexType = DIRECT;
  257.     indexInfoPtr->firstIndex = blockNum;
  258.     indexInfoPtr->blockAddr = fdPtr->direct[blockNum];
  259.     return(1);
  260.     }
  261.  
  262.     /*
  263.      * Is an indirect block.
  264.      */
  265.     blockNum -= FSDM_NUM_DIRECT_BLOCKS;
  266.     indirectBlock = blockNum / FSDM_INDICES_PER_BLOCK;
  267.     if (indirectBlock == 0) {
  268.     /*
  269.      * This is a singly indirect block.
  270.      */
  271.     indexInfoPtr->indexType = INDIRECT;
  272.     indexInfoPtr->firstIndex = blockNum;
  273.     } else {
  274.     /*
  275.      * This a doubly indirect block.
  276.      */
  277.     indexInfoPtr->indexType = DBL_INDIRECT;
  278.     indexInfoPtr->firstIndex = indirectBlock - 1;
  279.     indexInfoPtr->secondIndex = blockNum -
  280.                     indirectBlock * FSDM_INDICES_PER_BLOCK;
  281.     }
  282.  
  283.     /*
  284.      * Finish off by making the block pointer accessible.  This may include
  285.      * reading indirect blocks into the cache.
  286.      */
  287.     return(MakePtrAccessible(indexInfoPtr));
  288. }
  289.  
  290.  
  291. /*
  292.  *----------------------------------------------------------------------
  293.  *
  294.  * GetNextIndex --
  295.  *
  296.  *    Put the correct pointers in the index structure to access the
  297.  *    block after the current block.
  298.  *
  299.  * Results:
  300.  *    None.
  301.  *
  302.  * Side effects:
  303.  *    The allocation structure is modified.
  304.  *
  305.  *----------------------------------------------------------------------
  306.  */
  307. static int
  308. GetNextIndex(indexInfoPtr)
  309.     register DirIndexInfo *indexInfoPtr; /* Index structure to set up. */
  310. {
  311.     int            accessible = 0;
  312.     register Fsdm_FileDescriptor    *fdPtr;
  313.  
  314.     fdPtr = indexInfoPtr->fdPtr;
  315.  
  316.     indexInfoPtr->blockNum++;
  317.     indexInfoPtr->dirDirty = 0;
  318.  
  319.     /*
  320.      * Determine whether we are now in direct, indirect or doubly indirect
  321.      * blocks.
  322.      */
  323.     switch (indexInfoPtr->indexType) {
  324.     case DIRECT:
  325.         if (indexInfoPtr->blockNum < FSDM_NUM_DIRECT_BLOCKS) {
  326.         /*
  327.          * Still in the direct blocks.
  328.          */
  329.         indexInfoPtr->firstIndex++;
  330.         indexInfoPtr->blockAddr = 
  331.                 fdPtr->direct[indexInfoPtr->firstIndex];
  332.         accessible = 1;
  333.         } else {
  334.         /*
  335.          * Moved into indirect blocks.
  336.          */
  337.         indexInfoPtr->indexType = INDIRECT;
  338.         indexInfoPtr->firstIndex = 0;
  339.         }
  340.         break;
  341.     case INDIRECT:
  342.         if (indexInfoPtr->blockNum < FSDM_NUM_DIRECT_BLOCKS +
  343.             FSDM_INDICES_PER_BLOCK) {
  344.         /*
  345.          * Still in singly indirect blocks.
  346.          */
  347.         indexInfoPtr->firstIndex++;
  348.         indexInfoPtr->blockAddr = *(int *) (indexInfoPtr->firstBlock +
  349.                   sizeof(int) * indexInfoPtr->firstIndex);
  350.         accessible = 1;
  351.         break;
  352.        } else {
  353.         /*
  354.          * Moved into doubly indirect blocks.
  355.          */
  356.         indexInfoPtr->firstIndex = 0;
  357.         indexInfoPtr->secondIndex = 0;
  358.         indexInfoPtr->indexType = DBL_INDIRECT;
  359.         /*
  360.          * Free up the pointer block.
  361.          */
  362.         indexInfoPtr->firstBlockNil = 1;
  363.         }
  364.         break;
  365.     case DBL_INDIRECT:
  366.         indexInfoPtr->secondIndex++;
  367.         if (indexInfoPtr->secondIndex == FSDM_INDICES_PER_BLOCK) {
  368.         indexInfoPtr->firstIndex++;
  369.         indexInfoPtr->secondIndex = 0;
  370.         indexInfoPtr->secondBlockNil = 1;
  371.         } else {
  372.         indexInfoPtr->blockAddr = *(int *) (indexInfoPtr->secondBlock +
  373.                   sizeof(int) * indexInfoPtr->secondIndex);
  374.         accessible = 1;
  375.         }
  376.         break;
  377.     }
  378.  
  379.     /*
  380.      * Make the block pointers accessible if necessary.
  381.      */
  382.     if (!accessible) {
  383.     return(MakePtrAccessible(indexInfoPtr));
  384.     } else {
  385.     return(1);
  386.     }
  387. }
  388.  
  389.  
  390. /*
  391.  *----------------------------------------------------------------------
  392.  *
  393.  * OpenDir --
  394.  *
  395.  *    Set up the structure to allow moving through the given directory.
  396.  *
  397.  * Results:
  398.  *    None.
  399.  *
  400.  * Side effects:
  401.  *    The index structure is set up and *dirEntryPtrPtr set to point to
  402.  *    the first directory entry.
  403.  *
  404.  *----------------------------------------------------------------------
  405.  */
  406. static void
  407. OpenDir(fdPtr, fdInfoPtr, indexInfoPtr, dirEntryPtrPtr)
  408.     Fsdm_FileDescriptor    *fdPtr;        /* The file descriptor for the
  409.                      * directory. */
  410.     FdInfo        *fdInfoPtr;    /* Descriptor status info for the
  411.                      * directory. */
  412.     DirIndexInfo     *indexInfoPtr;    /* Index info struct */
  413.     Fslcl_DirEntry        **dirEntryPtrPtr; /* Where to return a pointer to
  414.                        * the first directory entry. */
  415. {
  416.     int            fragsToRead;
  417.  
  418.     if (fdPtr->lastByte == -1) {
  419.     /*
  420.      * Empty directory.
  421.      */
  422.     *dirEntryPtrPtr = (Fslcl_DirEntry *) NULL;
  423.     return;
  424.     } else if ((fdPtr->lastByte + 1) % FSLCL_DIR_BLOCK_SIZE != 0) {
  425.     fprintf(stderr,
  426.     "Directory not multiple of directory block size. Directory corrected.\n");
  427.     foundError = 1;
  428.     fdPtr->lastByte = (fdPtr->lastByte & ~(FSLCL_DIR_BLOCK_SIZE - 1)) +
  429.                 FSLCL_DIR_BLOCK_SIZE - 1;
  430.     fdInfoPtr->flags |= FD_MODIFIED;
  431.     }
  432.     /*
  433.      * Initialize the index structure.
  434.      */
  435.     indexInfoPtr->fdPtr = fdPtr;
  436.     indexInfoPtr->fdInfoPtr = fdInfoPtr;
  437.     if (!GetFirstIndex(0, indexInfoPtr)) {
  438.     fprintf(stderr, "OpenDir: Error setting up index\n");
  439.     *dirEntryPtrPtr = (Fslcl_DirEntry *) NULL;
  440.     return;
  441.     }
  442.     /*
  443.      * Read in the first directory block.
  444.      */
  445.     if (fdPtr->lastByte >= FS_BLOCK_SIZE - 1) {
  446.     fragsToRead = FS_FRAGMENTS_PER_BLOCK;
  447.     } else {
  448.     fragsToRead = fdPtr->lastByte / FS_FRAGMENT_SIZE + 1;
  449.     }
  450.     indexInfoPtr->numFrags = fragsToRead;
  451.     if (DiskRead(diskFd, 
  452.               indexInfoPtr->blockAddr, 
  453.               fragsToRead*FS_FRAGMENT_SIZE, indexInfoPtr->dirBlock) 
  454.               != fragsToRead*FS_FRAGMENT_SIZE) {
  455.     fprintf(stderr, "OpenDir: Read failed block %d\n",
  456.                indexInfoPtr->blockAddr); 
  457.     *dirEntryPtrPtr = (Fslcl_DirEntry *) NULL;
  458.     return;
  459.     } 
  460.     indexInfoPtr->dirOffset = 0;
  461.     *dirEntryPtrPtr = (Fslcl_DirEntry *) indexInfoPtr->dirBlock;
  462. }
  463.  
  464.  
  465. /*
  466.  *----------------------------------------------------------------------
  467.  *
  468.  * NextDirEntry --
  469.  *
  470.  *    Return a pointer to the next directory entry.
  471.  *
  472.  * Results:
  473.  *    None.
  474.  *
  475.  * Side effects:
  476.  *    The index structure is modified and *dirEntryPtrPtr set to point
  477.  *    to the next directory entry.
  478.  *
  479.  *----------------------------------------------------------------------
  480.  */
  481. static void
  482. NextDirEntry(indexInfoPtr, dirEntryPtrPtr)
  483.     DirIndexInfo     *indexInfoPtr;
  484.     Fslcl_DirEntry        **dirEntryPtrPtr;
  485. {
  486.     int            firstDirByte;
  487.     int            lastByte;
  488.     Fslcl_DirEntry        *dirEntryPtr;
  489.     int            fragsToRead;
  490.  
  491.     dirEntryPtr = *dirEntryPtrPtr;
  492.     indexInfoPtr->dirOffset += dirEntryPtr->recordLength;
  493.     lastByte = indexInfoPtr->fdPtr->lastByte;
  494.     firstDirByte = 
  495.      indexInfoPtr->dirOffset + indexInfoPtr->blockNum * FS_BLOCK_SIZE;
  496.     if (firstDirByte == lastByte + 1) {
  497.     /*
  498.      * We reached the end of the directory.  Write out the directory
  499.      * block if necessary.
  500.      */
  501.     *dirEntryPtrPtr = (Fslcl_DirEntry *) NULL;
  502.     return;
  503.     }
  504.  
  505.     if (indexInfoPtr->dirOffset < FS_BLOCK_SIZE) {
  506.     /*
  507.      * The next directory entry is in the current block.
  508.      */
  509.     dirEntryPtr = 
  510.          (Fslcl_DirEntry *) &(indexInfoPtr->dirBlock[indexInfoPtr->dirOffset]);
  511.     } else {
  512.     /*
  513.      * Have to move to the next directory block.  Write out the current
  514.      * block if necessary.
  515.      */
  516. #ifdef notdef
  517.     if (indexInfoPtr->dirDirty && writeDisk) {
  518.         *dirEntryPtrPtr = (Fslcl_DirEntry *) NULL;
  519.         }
  520.     }
  521. #endif
  522.     if (!GetNextIndex(indexInfoPtr)) {
  523.         fprintf(stderr, "NextDirEntry: Get index failed\n");
  524.         *dirEntryPtrPtr = (Fslcl_DirEntry *) NULL;
  525.         return;
  526.     }
  527.     if (lastByte - firstDirByte + 1 >= FS_BLOCK_SIZE ||
  528.         indexInfoPtr->blockNum >= FSDM_NUM_DIRECT_BLOCKS) {
  529.         fragsToRead = FS_FRAGMENTS_PER_BLOCK;
  530.     } else {
  531.         fragsToRead = (lastByte - firstDirByte) / FS_FRAGMENT_SIZE + 1;
  532.     }
  533.     indexInfoPtr->numFrags = fragsToRead;
  534.     if (DiskRead(diskFd,   indexInfoPtr->blockAddr,
  535.               fragsToRead*FS_FRAGMENT_SIZE, 
  536.               indexInfoPtr->dirBlock) != fragsToRead*FS_FRAGMENT_SIZE) {
  537.         fprintf(stderr, "NextDirEntry: Read failed block %d\n",
  538.                 indexInfoPtr->blockAddr); 
  539.         *dirEntryPtrPtr = (Fslcl_DirEntry *) NULL;
  540.         return;
  541.     }
  542.     indexInfoPtr->dirOffset = 0;
  543.     dirEntryPtr = (Fslcl_DirEntry *) indexInfoPtr->dirBlock;
  544.     }
  545.  
  546.     *dirEntryPtrPtr = dirEntryPtr;
  547. }
  548.  
  549. static    DirIndexInfo    lostDirIndex;
  550. static  Fslcl_DirEntry    *lostDirEntryPtr;
  551.  
  552. static    List_Links    orphanDirListHdr;
  553. static  List_Links    *orphanDirList = &orphanDirListHdr;
  554. typedef struct DirList {
  555.     List_Links    links;
  556.     int        dirNumber;
  557. } DirList;
  558.  
  559. /*
  560.  *----------------------------------------------------------------------
  561.  *
  562.  * CloseDir --
  563.  *
  564.  *    Flushes the current directory block to disk, if necessary.
  565.  *
  566.  * Results:
  567.  *    None.
  568.  *
  569.  * Side effects:
  570.  *    The index structure is modified and *dirEntryPtrPtr set to point
  571.  *    to the next directory entry.
  572.  *
  573.  *----------------------------------------------------------------------
  574.  */
  575. static void
  576. CloseDir(indexInfoPtr)
  577.     DirIndexInfo     *indexInfoPtr;
  578. {
  579.  
  580. #ifdef notdef
  581.     if (indexInfoPtr->dirDirty && writeDisk) {
  582.         return;
  583.     }
  584. #endif
  585. }
  586.  
  587.  
  588. /*
  589.  *----------------------------------------------------------------------
  590.  *
  591.  * CheckDirTree --
  592.  *
  593.  *    Traverse the directory tree taking care of unreferenced files and
  594.  *    ensuring that link counts are correct.
  595.  *
  596.  * Results:
  597.  *    A return status.
  598.  *
  599.  * Side effects:
  600.  *    None.
  601.  *
  602.  *----------------------------------------------------------------------
  603.  */
  604. void
  605. CheckDirTree(diskId)
  606.     int            diskId;
  607. {
  608.     register    int    i;
  609.     register FdInfo    *fdInfoPtr;
  610.     Fslcl_DirEntry        *dirEntryPtr;
  611.     DirIndexInfo    dirIndex;
  612.     int            lostRootDirNum = -1;
  613.     int            unrefFiles = 0;
  614.     int            linkCountsCorrected = 0;
  615.     int            entryNum;
  616.     int            notAdded;
  617.  
  618.  
  619.     diskFd = diskId;
  620.     /*
  621.      * Check the root directory for consistency.
  622.      */
  623.     if (!FetchFileDesc(FSDM_ROOT_FILE_NUMBER, &rootFDPtr)) {
  624.     fprintf(stderr, "Unable to fetch file descriptor for root");
  625.     exit(EXIT_HARD_ERROR);
  626.     }
  627.  
  628.     if ((rootFDPtr->flags & FSDM_FD_FREE) ||
  629.     rootFDPtr->fileType != FS_DIRECTORY ||
  630.     rootFDPtr->magic != FSDM_FD_MAGIC ||
  631.     rootFDPtr->lastByte == -1) {
  632.  
  633.     fprintf(stderr, "Root directory corrupted\n");
  634.         exit(EXIT_HARD_ERROR);
  635.     }
  636.     OpenDir(rootFDPtr, &descInfoArray[FSDM_ROOT_FILE_NUMBER], &dirIndex, 
  637.         &dirEntryPtr);
  638.     if (dirEntryPtr == (Fslcl_DirEntry *)NULL) {
  639.     exit(EXIT_HARD_ERROR);
  640.     }
  641.  
  642.     (void)strcpy(pathName, "/");
  643.     entryNum = 0;
  644.     while (dirEntryPtr != (Fslcl_DirEntry *) NULL) {
  645.     /*
  646.      * Go through the root directory checking each directory entry.
  647.      */
  648.     CheckDirEntry(entryNum, &dirIndex, dirEntryPtr);
  649.     if (dirEntryPtr->nameLength > 0 && 
  650.         strncmp("lost+found", dirEntryPtr->fileName,
  651.             dirEntryPtr->nameLength)  == 0) {
  652.         lostFoundFileNum = dirEntryPtr->fileNumber;
  653.     }
  654.     NextDirEntry(&dirIndex, &dirEntryPtr);
  655.     entryNum++;
  656.     }
  657.     CloseDir(&dirIndex);
  658.     if (tooBig) {
  659.     return;
  660.     }
  661.  
  662.     if (lostFoundFileNum == -1) {
  663.     fprintf(stderr, "lost+found missing from root\n");
  664.     lostFoundFileNum = -1;
  665.     } else {
  666.     /*
  667.      * Make sure that lost and found is consistent.
  668.      */
  669.     if (!FetchFileDesc(lostFoundFileNum, &lostFoundFDPtr)) {
  670.         fprintf(stderr, "Unable to fetch file descriptor for lost+found");
  671.         exit(EXIT_HARD_ERROR);
  672.     }
  673.  
  674.     (void)strcpy(pathName, "/lost+found/");
  675.     fdInfoPtr = &descInfoArray[lostFoundFileNum];
  676.     if (lostFoundFDPtr->fileType != FS_DIRECTORY) {
  677.         fprintf(stderr,
  678.          "Lost+found isn't a directory!  Should remove and recreate.\n");
  679.         lostFoundFileNum = -1;
  680.     } else {
  681.         int    dirOK;
  682.  
  683.         CheckDir(lostFoundFileNum, lostFoundFDPtr, fdInfoPtr,
  684.             FSDM_ROOT_FILE_NUMBER, lostRootDirNum,    &dirOK);
  685.         if (dirOK) {
  686.         OpenDir(lostFoundFDPtr, fdInfoPtr, &lostDirIndex,
  687.                  &lostDirEntryPtr);
  688.         if (lostDirEntryPtr == (Fslcl_DirEntry *)NULL) {
  689.             fprintf(stderr, "Could not open lost+found\n");
  690.             lostFoundFileNum = -1;
  691.         } else {
  692.             descInfoArray[lostFoundFileNum].flags |= FD_SEEN;
  693.         }
  694.         } else {
  695.         lostFoundFileNum = -1;
  696.         }
  697.     }
  698.     }
  699.  
  700.     if (tooBig) {
  701.     return;
  702.     }
  703.     /*
  704.      * Check all file descriptors.  If we are re-creating the root this
  705.      * has a side-effect of preparing a list of the orphans of the root.
  706.      */
  707.     for (i = 0, fdInfoPtr = descInfoArray;
  708.      i < superBlockPtr->descMap.maxDesc; 
  709.      i++, fdInfoPtr++) {
  710.     int            dirOK;
  711.     Fsdm_FileDescriptor    *newFDPtr;
  712.  
  713.     if (!(fdInfoPtr->flags & FD_ALLOCATED) ||
  714.          (fdInfoPtr->flags & FD_SEEN) ||
  715.         !(fdInfoPtr->flags & IS_A_DIRECTORY)) {
  716.         continue;
  717.     }
  718.     pathName[0] = '\0';
  719.     if (!FetchFileDesc(i, &newFDPtr)) {
  720.         fprintf(stderr,
  721.             "Unable to fetch file descriptor for directory <%d>.\n", i);
  722.         continue;
  723.     }
  724.     CheckDir(i, newFDPtr, fdInfoPtr, FSDM_ROOT_FILE_NUMBER,
  725.         lostRootDirNum, &dirOK);
  726. #ifdef notdef
  727.     StoreFileDesc(i, newFDPtr);
  728. #endif
  729.     }
  730.     if (tooBig) {
  731.     return;
  732.     }
  733.     /*
  734.      * Now go through the file descriptors again this time putting all
  735.      * unreferenced files in the lost and found directory and correcting
  736.      * link counts.
  737.      */
  738.     notAdded = 0;
  739.     for (i = 0, fdInfoPtr = descInfoArray;
  740.      i < superBlockPtr->descMap.maxDesc; 
  741.      i++, fdInfoPtr++) {
  742.  
  743.     /*
  744.      * We have to do lost+found last because its link count is changed
  745.      * when directories are added to it.
  746.      */
  747.  
  748.     if (i == lostFoundFileNum) {
  749.         continue;
  750.     } else if (i == superBlockPtr->descMap.maxDesc-1) {
  751.         if (lostFoundFileNum == -1) {
  752.         break;
  753.         }
  754.         i = lostFoundFileNum;
  755.         fdInfoPtr = &descInfoArray[lostFoundFileNum];
  756.     }
  757.     if (!(fdInfoPtr->flags & FD_ALLOCATED) ||
  758.         (fdInfoPtr->flags & FD_UNREADABLE) ||
  759.         i == FSDM_BAD_BLOCK_FILE_NUMBER) {
  760.         continue;
  761.     }
  762.  
  763.     if (!(fdInfoPtr->flags & FD_REFERENCED) && i != FSDM_ROOT_FILE_NUMBER) {
  764.         if (verbose) {
  765.         fprintf(stderr, "File %d is unreferenced\n", i);
  766.         }
  767.         unrefFiles++;
  768.         foundError = 1;
  769.         fflush(stderr);
  770. #ifdef notdef
  771.         if (lostFoundFileNum != -1) {
  772.         (void) sprintf(newFileName,"%d",i);
  773.  
  774.         if (AddToDirectory(lostFoundFileNum, lostFoundFDPtr, 
  775.                 &lostDirIndex, &lostDirEntryPtr, i, 
  776.                 newFileName, fdInfoPtr) == DIRFULL) {
  777.             if (notAdded == 0) {
  778.             fprintf(stderr, 
  779.                 "Directory #%d full.  Couldn't insert file.\n", 
  780.                 lostFoundFileNum);
  781.             }
  782.             notAdded++;
  783.         }
  784.         }
  785. #endif
  786.     } else if (fdInfoPtr->newLinkCount != fdInfoPtr->origLinkCount) {
  787.         if (verbose) {
  788.         fprintf(stderr,
  789.             "Link count corrected for file %d.  Is %d should be %d.\n", 
  790.             i, fdInfoPtr->origLinkCount, fdInfoPtr->newLinkCount);
  791.         }
  792.         linkCountsCorrected++;
  793.         foundError = 1;
  794.         fflush(stderr);
  795.         if (i == FSDM_ROOT_FILE_NUMBER) {
  796.         rootFDPtr->numLinks = fdInfoPtr->newLinkCount;
  797.         fdInfoPtr->flags |= FD_MODIFIED;
  798.         } else if (i == lostFoundFileNum) {
  799.         lostFoundFDPtr->numLinks = fdInfoPtr->newLinkCount;
  800.         fdInfoPtr->flags |= FD_MODIFIED;
  801.         } else {
  802.         Fsdm_FileDescriptor    *fdPtr;
  803.         if (!FetchFileDesc(i, &fdPtr)) {
  804.             fprintf(stderr,
  805.       "Unable to fetch file descriptor for file <%d> to update link count", i);
  806.         } else {
  807.             fdPtr->numLinks = fdInfoPtr->newLinkCount;
  808.             fdInfoPtr->flags |= FD_MODIFIED;
  809. #ifdef notdef
  810.             StoreFileDesc(i, fdPtr);
  811. #endif
  812.         }
  813.         }
  814.     }
  815.     if (i == lostFoundFileNum) {
  816.         break;
  817.     }
  818.     }
  819.     if (notAdded > 0) {
  820.     fprintf(stderr, "%d files not added to directory %d.\n", notAdded,
  821.         lostFoundFileNum);
  822.     }
  823.  
  824.     if (unrefFiles > 0) {
  825.     fprintf(stderr, "%d unreferenced files\n", unrefFiles);
  826.     }
  827.     if (linkCountsCorrected) {
  828.     fprintf(stderr, "%d links counts corrected\n",
  829.                linkCountsCorrected);
  830.     }
  831.  
  832. #ifdef notdef
  833.     if (lostFoundFileNum != - 1 && lostDirIndex.dirDirty && writeDisk) {
  834.     if (Disk_FragWrite(partFID, domainPtr,
  835.             lostDirIndex.blockAddr + domainPtr->dataOffset * 
  836.                 FS_FRAGMENTS_PER_BLOCK,
  837.                 lostDirIndex.numFrags, 
  838.                 lostDirIndex.dirBlock) < 0) {
  839.         OutputPerror("CheckDirTree: Write failed");
  840.         exit(EXIT_WRITE_FAILURE);
  841.     }
  842.     }
  843.  
  844.     StoreFileDesc(FSDM_ROOT_FILE_NUMBER, rootFDPtr);
  845.     if (lostFoundFileNum != -1) {
  846.     StoreFileDesc(lostFoundFileNum, lostFoundFDPtr);
  847.     }
  848. #endif
  849. }
  850.  
  851.  
  852. /*
  853.  *----------------------------------------------------------------------
  854.  *
  855. * CheckDir --
  856.  *
  857.  *    Descend the directory tree starting from the given file descriptor.
  858.  *
  859.  * Results:
  860.  *    None.
  861.  *
  862.  * Side effects:
  863.  *    None.
  864.  *
  865.  *----------------------------------------------------------------------
  866.  */
  867.  
  868. static void
  869. CheckDir(fdNum, fdPtr, fdInfoPtr, parentFdNum, lostDirNum, dirOKPtr)
  870.     int            fdNum;    /* Which file descriptor we are looking
  871.                        at. */
  872.     Fsdm_FileDescriptor    *fdPtr;        /* Pointer the file descriptor that
  873.                      * we are looking at. */
  874.     FdInfo        *fdInfoPtr;    /* Status of the file desc that we are
  875.                        looking at. */
  876.     int            parentFdNum;    /* File descriptor of parent directory.
  877.                      */
  878.     int            lostDirNum;    /* For re-creating trashed directories.
  879.                      * This routine will add to a list
  880.                      * of directories that were ref'ed
  881.                      * by this 'lost directory' */
  882.     int            *dirOKPtr;    /* Return 1 if the directory is
  883.                      * not corrupted. */
  884. {
  885.     Fslcl_DirEntry     *dirEntryPtr;
  886.     FdInfo     *newFDInfoPtr;
  887.     DirIndexInfo dirIndex;
  888.     int         entryNum;
  889.     int        nullIndex;
  890.  
  891.     fdInfoPtr->flags |= FD_SEEN;
  892.     *dirOKPtr = 0;
  893.  
  894.     /*
  895.      * Open the directory.
  896.      */
  897.     OpenDir(fdPtr, fdInfoPtr, &dirIndex, &dirEntryPtr);
  898.     nullIndex = strlen(pathName);
  899.     if (dirEntryPtr == (Fslcl_DirEntry *) NULL) {    
  900.     fprintf(stderr, "Empty directory %d %s changed to a file.\n",
  901.                 fdNum, pathName);
  902.     foundError = 1;
  903.     fdPtr->fileType = FS_FILE;
  904.     fdInfoPtr->flags |= FD_MODIFIED;
  905.     return;
  906.     }
  907.     /*
  908.      * Go through the directory.
  909.      */
  910.     entryNum = 0;
  911.     if (debug) {
  912.     fprintf(stderr,"Working on %s\n",pathName);
  913.     }
  914.     do {
  915.     CheckDirEntry(entryNum, &dirIndex, dirEntryPtr);
  916.     if (entryNum == 0) {
  917.         /*
  918.          * This should be "." and should point to the directory that
  919.          * we are checking.
  920.          */
  921.         if (dirEntryPtr->fileNumber == 0 ||
  922.         strncmp(".", dirEntryPtr->fileName, 
  923.             dirEntryPtr->nameLength)  != 0) {
  924.         fprintf(stderr,
  925.             ". missing in directory %d %s.  Changed to a file.\n",
  926.                    fdNum, pathName);
  927.         foundError = 1;
  928.         fdPtr->fileType = FS_FILE;
  929.         fdInfoPtr->flags |= FD_MODIFIED;
  930.         fdInfoPtr->flags &= ~IS_A_DIRECTORY;
  931.         return;
  932.         }
  933.         if (dirEntryPtr->fileNumber != fdNum) {
  934.         fprintf(stderr, 
  935.                 ". does not point to self for directory %d %s\n",
  936.                 fdNum, pathName);
  937.         foundError = 1;
  938.         dirEntryPtr->fileNumber = fdNum;
  939.         dirIndex.dirDirty = 1;
  940.         }
  941.         fdInfoPtr->newLinkCount++;
  942.     } else if (entryNum == 1) {
  943.         /*
  944.          * This should be ".."
  945.          */
  946.         if (dirEntryPtr->fileNumber == 0 ||
  947.         strncmp("..", dirEntryPtr->fileName, 
  948.             dirEntryPtr->nameLength) != 0) {
  949.         fprintf(stderr,
  950.             ".. missing in directory %d %s.  Changed to a file.\n",
  951.                    fdNum, pathName);
  952.         foundError = 1;
  953.         fdPtr->fileType = FS_FILE;
  954.         fdInfoPtr->flags |= FD_MODIFIED;
  955.         fdInfoPtr->flags &= ~IS_A_DIRECTORY;
  956.         return;
  957.         }
  958.         if (dirEntryPtr->fileNumber != parentFdNum) {
  959.         fprintf(stderr, 
  960.             ".. in directory %d %s pointed to %d, changed to %d.\n",
  961.             fdNum, pathName, dirEntryPtr->fileNumber, parentFdNum);
  962.         foundError = 1;
  963.         dirEntryPtr->fileNumber = parentFdNum;
  964.         dirIndex.dirDirty = 1;
  965.         }
  966.         /*
  967.          * Look for orphans of lost directories.
  968.          */
  969.         if (lostDirNum > 0 &&
  970.         dirEntryPtr->fileNumber == lostDirNum &&
  971.         (fdNum != FSDM_ROOT_FILE_NUMBER ||
  972.         lostDirNum != FSDM_ROOT_FILE_NUMBER)) {
  973.         DirList *dirListPtr;
  974.         Alloc(dirListPtr,DirList,1);
  975.         if (!tooBig) {
  976.             dirListPtr->dirNumber = fdNum;
  977.             fprintf(stderr, "Found #%d, an orphan of dir #%d\n", 
  978.                 fdNum, lostDirNum);
  979.             List_Insert((List_Links *)dirListPtr,
  980.                 LIST_ATREAR(orphanDirList));
  981.             fdInfoPtr->flags |= FD_REFERENCED;
  982.             fdInfoPtr->newLinkCount++;
  983.         }
  984.         } else {
  985.         descInfoArray[dirEntryPtr->fileNumber].newLinkCount++;
  986.         }
  987.     } else if (dirEntryPtr->fileNumber != 0) {
  988.         newFDInfoPtr = &descInfoArray[dirEntryPtr->fileNumber];
  989.         newFDInfoPtr->newLinkCount++;
  990.         newFDInfoPtr->flags |= FD_REFERENCED;
  991.         if (!(newFDInfoPtr->flags & FD_SEEN) &&
  992.            (newFDInfoPtr->flags & IS_A_DIRECTORY)) {
  993.         int    dirOK;
  994.         Fsdm_FileDescriptor    *newFDPtr;
  995.  
  996.         /*
  997.          * Recurse on the directory.
  998.          */
  999.         (void)strncat(pathName, dirEntryPtr->fileName,
  1000.                   dirEntryPtr->nameLength);
  1001.         (void)strcat(pathName, "/");
  1002.         if (!FetchFileDesc(dirEntryPtr->fileNumber, &newFDPtr)) {
  1003.             fprintf(stderr,
  1004.             "Unable to fetch file descriptor for directory <%d>.\n",
  1005.                   dirEntryPtr->fileNumber);
  1006.         } else {
  1007.             CheckDir(dirEntryPtr->fileNumber, newFDPtr, 
  1008.                  newFDInfoPtr, fdNum, lostDirNum, &dirOK);
  1009.             pathName[nullIndex] = '\0';
  1010. #ifdef notdef
  1011.             StoreFileDesc(dirEntryPtr->fileNumber, newFDPtr);
  1012. #endif
  1013.         }
  1014.         } 
  1015.     }
  1016.     NextDirEntry(&dirIndex, &dirEntryPtr);
  1017.     entryNum++;
  1018.     } while (dirEntryPtr != (Fslcl_DirEntry *) NULL);
  1019.  
  1020.     *dirOKPtr = 1;
  1021. }
  1022.  
  1023.  
  1024. /*
  1025.  *----------------------------------------------------------------------
  1026.  *
  1027.  * CheckDirEntry --
  1028.  *
  1029.  *    Perform checks on the current directory entry to make sure that
  1030.  *    it is has not been trashed.
  1031.  *
  1032.  * Results:
  1033.  *    None.
  1034.  *
  1035.  * Side effects:
  1036.  *    The directory may be modified.
  1037.  *
  1038.  *----------------------------------------------------------------------
  1039.  */
  1040.  
  1041. void
  1042. CheckDirEntry(entryNum, dirIndexPtr, dirEntryPtr)
  1043.     int        entryNum;    
  1044.     register    DirIndexInfo    *dirIndexPtr;
  1045.     register    Fslcl_DirEntry    *dirEntryPtr;
  1046. {
  1047.     int            dirBlockOffset;
  1048.     int            lastDirByte;
  1049.     char        buf[FS_MAX_NAME_LENGTH + 1];
  1050.     int            nameLength;
  1051.     register    char    *strPtr;
  1052.     int hadError = 0;
  1053.  
  1054.     dirBlockOffset = dirIndexPtr->dirOffset & (FSLCL_DIR_BLOCK_SIZE - 1);
  1055.     lastDirByte = dirBlockOffset + dirEntryPtr->recordLength;
  1056.  
  1057.     if (dirEntryPtr->fileNumber == 0) {
  1058.     nameLength = 0;
  1059.     } else {
  1060.     nameLength = dirEntryPtr->nameLength;
  1061.     }
  1062.  
  1063.     /*
  1064.      * First check the record length.
  1065.      */
  1066.     if (lastDirByte > FSLCL_DIR_BLOCK_SIZE ||
  1067.     lastDirByte % FSLCL_REC_LEN_GRAIN != 0 || 
  1068.     (FSLCL_DIR_BLOCK_SIZE - lastDirByte < FSLCL_DIR_ENTRY_HEADER &&
  1069.      lastDirByte != FSLCL_DIR_BLOCK_SIZE) ||
  1070.     dirEntryPtr->recordLength < Fslcl_DirRecLength(nameLength) ||
  1071.     dirEntryPtr->recordLength < 0) {
  1072.     fprintf(stderr,
  1073.     "Bad record length in directory.  Directory entry deleted from %s\n",
  1074.                pathName);
  1075.     foundError = 1;
  1076.     hadError = 1;
  1077.     /*
  1078.      * If the record length is screwed up, extend this record to the end
  1079.      * of the directory block and zap the file number.
  1080.      */
  1081.     dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE - dirBlockOffset;
  1082.     dirEntryPtr->fileNumber = 0;
  1083.     dirIndexPtr->dirDirty = 1;
  1084.     return;
  1085.     }
  1086.     /*
  1087.      * Check the name length.
  1088.      */
  1089.     if (dirEntryPtr->fileNumber != 0) {
  1090.     int    nameError = 0;
  1091.     nameLength = strnlen(dirEntryPtr->fileName,
  1092.                  dirEntryPtr->recordLength - FSLCL_DIR_ENTRY_HEADER);
  1093.     if (nameLength != dirEntryPtr->nameLength) {
  1094.         bcopy(dirEntryPtr->fileName, buf, nameLength);
  1095.         buf[nameLength] = '\0';
  1096.         fprintf(stderr,
  1097.         "Name length %d wrong for directory entry: %s. Should be %d.\n", 
  1098.         dirEntryPtr->nameLength, buf, nameLength);
  1099.         foundError = 1;
  1100.         hadError = 1;
  1101.         dirEntryPtr->nameLength = nameLength;
  1102.         dirIndexPtr->dirDirty = 1;
  1103.         dirEntryPtr->recordLength = Fslcl_DirRecLength(nameLength);
  1104.     }
  1105.     /*
  1106.      * Make sure that the name contains printable characters.
  1107.      */
  1108.     strPtr = dirEntryPtr->fileName;
  1109.     while (*strPtr != '\0') {
  1110.         if (*strPtr < 0 || !isprint(*strPtr)) {
  1111.         *strPtr = '?';
  1112.         nameError = 1;
  1113.         }
  1114.         strPtr++;
  1115.     }
  1116.     if (nameError) {
  1117.         dirIndexPtr->dirDirty = 1;
  1118.         fprintf(stderr,
  1119.           "Non-printable characters in name for file %d in directory %s\n",
  1120.           dirEntryPtr->fileNumber, pathName);
  1121.         foundError = 1;
  1122.         hadError = 1;
  1123.     }
  1124.     }
  1125.  
  1126.     /*
  1127.      * Now check the file number.
  1128.      */
  1129.     if (dirEntryPtr->fileNumber < 0 ||
  1130.         dirEntryPtr->fileNumber >= superBlockPtr->descMap.maxDesc) {
  1131.     fprintf(stderr, 
  1132.     "Bad file number in directory.  Directory entry deleted from %s.\n", 
  1133.                pathName);
  1134.     foundError = 1;
  1135.     hadError = 1;
  1136.     dirEntryPtr->fileNumber = 0;
  1137.     dirIndexPtr->dirDirty = 1;
  1138.     /*
  1139.      * Here we want to allow the ".." entry (entryNum = 0) to reference a
  1140.      * non-allocated file descriptor. What we have is an orphan directory so
  1141.      * we shouldn't nuke it just because something bad happened to its parent.
  1142.      */
  1143.     } else if (dirEntryPtr->fileNumber != 0 &&
  1144.               !(descInfoArray[dirEntryPtr->fileNumber].flags & FD_ALLOCATED) &&
  1145.           entryNum != 1)
  1146.           {
  1147.     fprintf(stderr, 
  1148.         "File %s%s references non-allocated descriptor %d. File Deleted.\n",
  1149.         pathName, dirEntryPtr->fileName,dirEntryPtr->fileNumber);
  1150.     foundError = 1;
  1151.     hadError = 1;
  1152.     dirEntryPtr->fileNumber = 0;
  1153.     dirIndexPtr->dirDirty = 1;
  1154.     }
  1155.     if (!hadError && debug) {
  1156.     fprintf(stderr,"Entry %s ok.\n",dirEntryPtr->fileName);
  1157.     }
  1158.     if (hadError) {
  1159.     fprintf(stderr,
  1160.     "Entry %s (%d) now has nameLength %d, recordLength %d, fileNumber %d.\n",
  1161.     dirEntryPtr->fileName, entryNum, dirEntryPtr->nameLength, 
  1162.     dirEntryPtr->recordLength, dirEntryPtr->fileNumber);
  1163.     }
  1164. }
  1165. #ifdef notdef
  1166.  
  1167.  
  1168. /*
  1169.  *----------------------------------------------------------------------
  1170.  *
  1171.  * SetDotDot --
  1172.  *
  1173.  *    Make ".." in the given directory point to a given directory.
  1174.  *
  1175.  * Results:
  1176.  *    None.
  1177.  *
  1178.  * Side effects:
  1179.  *    ".." in the given directory is set to point to lost and found.
  1180.  *
  1181.  *----------------------------------------------------------------------
  1182.  */
  1183. static int
  1184. SetDotDot(dirNumber, dirFDPtr, fdPtr, fdInfoPtr)
  1185.     int            dirNumber;
  1186.     Fsdm_FileDescriptor    *dirFDPtr;
  1187.     Fsdm_FileDescriptor    *fdPtr;
  1188.     FdInfo        *fdInfoPtr;
  1189. {
  1190.     Fslcl_DirEntry         *dirEntryPtr;
  1191.     DirIndexInfo     dirIndex;
  1192.  
  1193.     /*
  1194.      * Open the directory.
  1195.      */
  1196.     OpenDir(fdPtr, fdInfoPtr, &dirIndex, &dirEntryPtr);
  1197.     if (dirEntryPtr == (Fslcl_DirEntry *)NULL) {
  1198.     fprintf(stderr, "SetDotDot: Could not open dir\n");
  1199.     return(0);
  1200.     }
  1201.     /*
  1202.      * Move past "." to "..".  Note that it is assume that this directory
  1203.      * has been checked and thus has both "." and "..".
  1204.      */
  1205.     NextDirEntry(&dirIndex, &dirEntryPtr);
  1206.     if (dirEntryPtr == (Fslcl_DirEntry *)NULL) {
  1207.     fprintf(stderr, "SetDotDot: Could not move from . to ..\n");
  1208.     return(0);
  1209.     }
  1210.  
  1211.     descInfoArray[dirNumber].newLinkCount++;
  1212.     descInfoArray[dirNumber].flags |= FD_MODIFIED;
  1213.     dirEntryPtr->fileNumber = dirNumber;
  1214.     if (writeDisk) {
  1215.     if (Disk_FragWrite(partFID, domainPtr, 
  1216.        dirIndex.blockAddr + domainPtr->dataOffset * FS_FRAGMENTS_PER_BLOCK,
  1217.        dirIndex.numFrags, dirIndex.dirBlock) < 0) {
  1218.         fprintf(stderr, "SetDotDot: Write failed block %d\n",
  1219.             dirIndex.blockAddr + 
  1220.                 domainPtr->dataOffset * FS_FRAGMENTS_PER_BLOCK);
  1221.         return(0);
  1222.     }
  1223.     }
  1224.     return(1);
  1225. }
  1226.  
  1227. /*
  1228.  *----------------------------------------------------------------------
  1229.  *
  1230.  * AddToDirectory --
  1231.  *
  1232.  *    Add the file descriptor to a directory.  
  1233.  *
  1234.  * Results:
  1235.  *    None.
  1236.  *
  1237.  * Side effects:
  1238.  *    The directory is modified to contain the orphaned file.
  1239.  *
  1240.  *----------------------------------------------------------------------
  1241.  */
  1242. static ReturnStatus
  1243. AddToDirectory(dirNumber, dirFDPtr, dirIndexPtr, dirEntryPtrPtr, fileNumber,
  1244.     fileName, fdInfoPtr)
  1245.     int            dirNumber;
  1246.     Fsdm_FileDescriptor    *dirFDPtr;
  1247.     DirIndexInfo    *dirIndexPtr;
  1248.     Fslcl_DirEntry        **dirEntryPtrPtr;
  1249.     int             fileNumber;
  1250.     char         *fileName;
  1251.     register    FdInfo    *fdInfoPtr;
  1252. {
  1253.     int             nameLength;
  1254.     int             recordLength;
  1255.     int             leftOver;
  1256.     int            oldRecLength;
  1257.     Fslcl_DirEntry        *dirEntryPtr;
  1258.     Fsdm_FileDescriptor    *fdPtr;
  1259.  
  1260.     adding = 1;
  1261.     nameLength = strlen(fileName);
  1262.     recordLength = Fslcl_DirRecLength(nameLength);
  1263.  
  1264.     dirEntryPtr = *dirEntryPtrPtr;
  1265.     while (dirEntryPtr != (Fslcl_DirEntry *) NULL) {
  1266.     if (dirEntryPtr->fileNumber != 0) {
  1267.         oldRecLength = Fslcl_DirRecLength(dirEntryPtr->nameLength);
  1268.         leftOver = dirEntryPtr->recordLength - oldRecLength;
  1269.         if (leftOver >= recordLength) {
  1270.         dirEntryPtr->recordLength = oldRecLength;
  1271.         dirEntryPtr = 
  1272.             (Fslcl_DirEntry *) ((int) dirEntryPtr + oldRecLength);
  1273.         dirEntryPtr->recordLength = leftOver;
  1274.         dirIndexPtr->dirOffset += oldRecLength;
  1275.         } else {
  1276.         NextDirEntry(dirIndexPtr, &dirEntryPtr);
  1277.         continue;
  1278.         }
  1279.     } else if (dirEntryPtr->recordLength < recordLength) {
  1280.         NextDirEntry(dirIndexPtr, &dirEntryPtr);
  1281.         continue;
  1282.     }
  1283.  
  1284.     if (!FetchFileDesc(fileNumber, &fdPtr)) {
  1285.         fprintf(stderr,
  1286.      "Unable to fetch file descriptor for file <%d> to add to directory <%d>\n",
  1287.               fileNumber, dirNumber);
  1288.         return FAILURE;
  1289.     }
  1290.     if (fdInfoPtr->flags & IS_A_DIRECTORY) {
  1291.         if (!SetDotDot(dirNumber, dirFDPtr, fdPtr, fdInfoPtr)) {
  1292.         *dirEntryPtrPtr = dirEntryPtr;
  1293.         return FAILURE;
  1294.         }
  1295.     }
  1296.     fdPtr->numLinks = fdInfoPtr->newLinkCount + 1;
  1297.     fdInfoPtr->flags |= FD_MODIFIED;
  1298.     StoreFileDesc(fileNumber, fdPtr);
  1299.  
  1300.     dirEntryPtr->fileNumber = fileNumber;
  1301.     dirEntryPtr->nameLength = nameLength;
  1302.     dirIndexPtr->dirDirty = 1;
  1303.     (void)strcpy(dirEntryPtr->fileName, fileName);
  1304.     leftOver = dirEntryPtr->recordLength - recordLength;
  1305.     if (leftOver > FSLCL_DIR_ENTRY_HEADER) {
  1306.         dirEntryPtr->recordLength = recordLength;
  1307.         dirEntryPtr =(Fslcl_DirEntry *) ((int) dirEntryPtr + recordLength);
  1308.         dirEntryPtr->fileNumber = 0;
  1309.         dirEntryPtr->recordLength = leftOver;
  1310.         dirIndexPtr->dirOffset += recordLength;
  1311.     } else {
  1312.         NextDirEntry(dirIndexPtr, &dirEntryPtr);
  1313.     }
  1314.     *dirEntryPtrPtr = dirEntryPtr;
  1315.     return SUCCESS;
  1316.     }
  1317.     return DIRFULL;
  1318. }
  1319.  
  1320. /*
  1321.  *----------------------------------------------------------------------
  1322.  *
  1323.  * MakeRoot --
  1324.  *
  1325.  *    Set up the file descriptor for the root directory.
  1326.  *
  1327.  * Results:
  1328.  *    Fill in the file descriptor.
  1329.  *
  1330.  * Side effects:
  1331.  *    Marks block 0 in the bitmap as in use.
  1332.  *
  1333.  *----------------------------------------------------------------------
  1334.  */
  1335. ReturnStatus
  1336. MakeRoot(domainPtr, bitmapPtr, fdPtr)
  1337.     Ofs_DomainHeader        *domainPtr;    /* Ptr to domain info */
  1338.     u_char            *bitmapPtr;    /* Ptr to cylinder data block
  1339.                          * bitmap */
  1340.     Fsdm_FileDescriptor        *fdPtr;
  1341. {
  1342.     Time     time;
  1343.     int     index;
  1344.     u_char     *bytePtr;
  1345.  
  1346.     fdPtr->flags = FSDM_FD_ALLOC;
  1347.     fdPtr->fileType = FS_DIRECTORY;
  1348.     fdPtr->permissions = 0755;
  1349.     fdPtr->uid = 0;
  1350.     fdPtr->gid = 0;
  1351.     fdPtr->lastByte = FS_BLOCK_SIZE-1;
  1352.     fdPtr->firstByte = -1;
  1353.     fdPtr->numLinks = 3;
  1354.     /*
  1355.      * Can't know device information because that depends on
  1356.      * the way the system is configured.
  1357.      */
  1358.     fdPtr->devServerID  -1;
  1359.     fdPtr->devType = -1;
  1360.     fdPtr->devUnit = -1;
  1361.  
  1362.     /*
  1363.      * Set the time stamps.  This assumes that universal time, not local
  1364.      * time, is used for time stamps.
  1365.      */
  1366.     Sys_GetTimeOfDay(&time, NULL, NULL);
  1367.     fdPtr->createTime = time.seconds;
  1368.     fdPtr->accessTime = 0;
  1369.     fdPtr->descModifyTime = time.seconds;
  1370.     fdPtr->dataModifyTime = time.seconds;
  1371.  
  1372.     /*
  1373.      * Place the data in the first filesystem block.
  1374.      */
  1375.     fdPtr->direct[0] = 0;
  1376.     bytePtr = GetBitmapPtr(domainPtr, bitmapPtr, 0);
  1377.     *bytePtr |= 0xf0;
  1378.     for (index = 1; index < FSDM_NUM_DIRECT_BLOCKS ; index++) {
  1379.     fdPtr->direct[index] = FSDM_NIL_INDEX;
  1380.     }
  1381.     for (index = 0; index < FSDM_NUM_INDIRECT_BLOCKS ; index++) {
  1382.     fdPtr->indirect[index] = FSDM_NIL_INDEX;
  1383.     }
  1384.     fdPtr->numKbytes = 4;
  1385.     fdPtr->version = 1;
  1386.     return SUCCESS;
  1387. }
  1388. #endif
  1389.  
  1390. /*
  1391.  *----------------------------------------------------------------------
  1392.  *
  1393.  * strnlen --
  1394.  *
  1395.  *    This is identical to strlen except that it will return N
  1396.  *    if the string length reaches N.
  1397.  *
  1398.  * Results:
  1399.  *    The return value is the number of characters in the
  1400.  *    string, not including the terminating zero byte.
  1401.  *
  1402.  * Side effects:
  1403.  *    None.
  1404.  *
  1405.  *----------------------------------------------------------------------
  1406.  */
  1407. int
  1408. strnlen(string, numChars)
  1409.     register char *string;        /* String whose length is wanted. */
  1410.     int           numChars;        /* Maximum number of chars to check. */
  1411. {
  1412.     register int result = -1;
  1413.  
  1414.     do {
  1415.     result += 1;
  1416.     } while (result < numChars && *string++ != 0);
  1417.     return(result);
  1418. }
  1419.